Change DOM0_PERFCCONTROL: remove array limit.
authorkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 7 Aug 2006 14:53:06 +0000 (15:53 +0100)
committerkaf24@firebug.cl.cam.ac.uk <kaf24@firebug.cl.cam.ac.uk>
Mon, 7 Aug 2006 14:53:06 +0000 (15:53 +0100)
Descriptors and values are passed by two distinct buffers.

Signed-off-by: Tristan Gingold <tristan.gingold@bull.net>
tools/libxc/xc_misc.c
tools/libxc/xenctrl.h
tools/misc/xenperf.c
xen/common/perfc.c
xen/include/public/dom0_ops.h

index 4c0cb24b90849149bc2e984b8edf6acb8c49e865..5a63e9e7194608e258b256cce993263d47e825e0 100644 (file)
@@ -68,7 +68,10 @@ int xc_sched_id(int xc_handle,
 
 int xc_perfc_control(int xc_handle,
                      uint32_t opcode,
-                     xc_perfc_desc_t *desc)
+                     xc_perfc_desc_t *desc,
+                     xc_perfc_val_t *val,
+                     int *nbr_desc,
+                     int *nbr_val)
 {
     int rc;
     DECLARE_DOM0_OP;
@@ -76,10 +79,16 @@ int xc_perfc_control(int xc_handle,
     op.cmd = DOM0_PERFCCONTROL;
     op.u.perfccontrol.op   = opcode;
     set_xen_guest_handle(op.u.perfccontrol.desc, desc);
+    set_xen_guest_handle(op.u.perfccontrol.val, val);
 
     rc = do_dom0_op(xc_handle, &op);
 
-    return (rc == 0) ? op.u.perfccontrol.nr_counters : rc;
+    if (nbr_desc)
+        *nbr_desc = op.u.perfccontrol.nr_counters;
+    if (nbr_val)
+        *nbr_val = op.u.perfccontrol.nr_vals;
+
+    return rc;
 }
 
 long long xc_msr_read(int xc_handle, int cpu_mask, int msr)
index a405171279a674e163410b7144b5b934bd64986d..58bf7b2dcb67ab55d32e294d0d099da46820034b 100644 (file)
@@ -466,10 +466,15 @@ unsigned long xc_make_page_below_4G(int xc_handle, uint32_t domid,
                                     unsigned long mfn);
 
 typedef dom0_perfc_desc_t xc_perfc_desc_t;
-/* IMPORTANT: The caller is responsible for mlock()'ing the @desc array. */
+typedef dom0_perfc_val_t xc_perfc_val_t;
+/* IMPORTANT: The caller is responsible for mlock()'ing the @desc and @val
+   arrays. */
 int xc_perfc_control(int xc_handle,
                      uint32_t op,
-                     xc_perfc_desc_t *desc);
+                     xc_perfc_desc_t *desc,
+                     xc_perfc_val_t *val,
+                     int *nbr_desc,
+                     int *nbr_val);
 
 /* read/write msr */
 long long xc_msr_read(int xc_handle, int cpu_mask, int msr);
index 1572780c3de0b5524ac748345d40cb8a3f94ad04..1054d022f77f3a875ab60270e1239cbdb990cc36 100644 (file)
@@ -22,7 +22,10 @@ int main(int argc, char *argv[])
 {
     int              i, j, xc_handle;
     xc_perfc_desc_t *pcd;
-    unsigned int     num, sum, reset = 0, full = 0;
+       xc_perfc_val_t  *pcv;
+       xc_perfc_val_t  *val;
+       int num_desc, num_val;
+    unsigned int    sum, reset = 0, full = 0;
 
     if ( argc > 1 )
     {
@@ -62,7 +65,7 @@ int main(int argc, char *argv[])
     if ( reset )
     {
         if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_RESET,
-                              NULL) < 0 )
+                              NULL, NULL, NULL, NULL) != 0 )
         {
             fprintf(stderr, "Error reseting performance counters: %d (%s)\n",
                     errno, strerror(errno));
@@ -72,47 +75,54 @@ int main(int argc, char *argv[])
         return 0;
     }
 
+       if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+                                                 NULL, NULL, &num_desc, &num_val) != 0 )
+        {
+            fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
+                    errno, strerror(errno));
+            return 1;
+        }
 
-    if ( (num = xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
-                                 NULL)) < 0 )
-    {
-        fprintf(stderr, "Error getting number of perf counters: %d (%s)\n",
-                errno, strerror(errno));
-        return 1;
-    }
-
-    pcd = malloc(sizeof(*pcd) * num);
+    pcd = malloc(sizeof(*pcd) * num_desc);
+       pcv = malloc(sizeof(*pcv) * num_val);
 
-    if ( mlock(pcd, sizeof(*pcd) * num) != 0 )
+    if ( pcd == NULL
+                || mlock(pcd, sizeof(*pcd) * num_desc) != 0
+                || pcv == NULL
+                || mlock(pcd, sizeof(*pcv) * num_val) != 0)
     {
-        fprintf(stderr, "Could not mlock descriptor buffer: %d (%s)\n",
+        fprintf(stderr, "Could not alloc or mlock buffers: %d (%s)\n",
                 errno, strerror(errno));
         exit(-1);
     }
 
-    if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY, pcd) <= 0 )
+    if ( xc_perfc_control(xc_handle, DOM0_PERFCCONTROL_OP_QUERY,
+                                                 pcd, pcv, NULL, NULL) != 0 )
     {
-        fprintf(stderr, "Error getting perf counter description: %d (%s)\n",
+        fprintf(stderr, "Error getting perf counter: %d (%s)\n",
                 errno, strerror(errno));
         return 1;
     }
 
-    munlock(pcd, sizeof(*pcd) * num);
+    munlock(pcd, sizeof(*pcd) * num_desc);
+    munlock(pcv, sizeof(*pcv) * num_val);
 
-    for ( i = 0; i < num; i++ )
+       val = pcv;
+    for ( i = 0; i < num_desc; i++ )
     {
         printf ("%-35s ", pcd[i].name);
         
         sum = 0;
         for ( j = 0; j < pcd[i].nr_vals; j++ )
-            sum += pcd[i].vals[j];
+            sum += val[j];
         printf ("T=%10u ", (unsigned int)sum);
 
         if ( full || (pcd[i].nr_vals <= 4) )
             for ( j = 0; j < pcd[i].nr_vals; j++ )
-                printf(" %10u", (unsigned int)pcd[i].vals[j]);
+                printf(" %10u", (unsigned int)val[j]);
 
         printf("\n");
+               val += pcd[i].nr_vals;
     }
 
     return 0;
index 830e1876b505d8e7afe98c8030916edb2bfd2df6..e2ba33383e39876925e829fa837aef7f4ba6df72 100644 (file)
@@ -136,10 +136,14 @@ void perfc_reset(unsigned char key)
 }
 
 static dom0_perfc_desc_t perfc_d[NR_PERFCTRS];
+static dom0_perfc_val_t *perfc_vals;
+static int               perfc_nbr_vals;
 static int               perfc_init = 0;
-static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc)
+static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc,
+                           XEN_GUEST_HANDLE(dom0_perfc_val_t) val)
 {
     unsigned int i, j;
+    unsigned int v = 0;
     atomic_t *counters = (atomic_t *)&perfcounters;
 
     if ( guest_handle_is_null(desc) )
@@ -169,13 +173,13 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc)
                 perfc_d[i].nr_vals = perfc_info[i].nr_elements;
                 break;
             }
-
-            if ( perfc_d[i].nr_vals > ARRAY_SIZE(perfc_d[i].vals) )
-                perfc_d[i].nr_vals = ARRAY_SIZE(perfc_d[i].vals);
+            perfc_nbr_vals += perfc_d[i].nr_vals;
         }
-
+        perfc_vals = xmalloc_array(dom0_perfc_val_t, perfc_nbr_vals);
         perfc_init = 1;
     }
+    if (perfc_vals == NULL)
+        return -ENOMEM;
 
     /* We gather the counts together every time. */
     for ( i = 0; i < NR_PERFCTRS; i++ )
@@ -184,26 +188,30 @@ static int perfc_copy_info(XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc)
         {
         case TYPE_SINGLE:
         case TYPE_S_SINGLE:
-            perfc_d[i].vals[0] = atomic_read(&counters[0]);
+            perfc_vals[v++] = atomic_read(&counters[0]);
             counters += 1;
             break;
         case TYPE_CPU:
         case TYPE_S_CPU:
             for ( j = 0; j < perfc_d[i].nr_vals; j++ )
-                perfc_d[i].vals[j] = atomic_read(&counters[j]);
+                perfc_vals[v++] = atomic_read(&counters[j]);
             counters += NR_CPUS;
             break;
         case TYPE_ARRAY:
         case TYPE_S_ARRAY:
             for ( j = 0; j < perfc_d[i].nr_vals; j++ )
-                perfc_d[i].vals[j] = atomic_read(&counters[j]);
+                perfc_vals[v++] = atomic_read(&counters[j]);
             counters += perfc_info[i].nr_elements;
             break;
         }
     }
+    BUG_ON(v != perfc_nbr_vals);
 
-    return (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS) ?
-            -EFAULT : 0);
+    if (copy_to_guest(desc, (dom0_perfc_desc_t *)perfc_d, NR_PERFCTRS))
+        return -EFAULT;
+    if (copy_to_guest(val, perfc_vals, perfc_nbr_vals))
+        return -EFAULT;
+    return 0;
 }
 
 /* Dom0 control of perf counters */
@@ -213,20 +221,18 @@ int perfc_control(dom0_perfccontrol_t *pc)
     u32 op = pc->op;
     int rc;
 
-    pc->nr_counters = NR_PERFCTRS;
-
     spin_lock(&lock);
 
     switch ( op )
     {
     case DOM0_PERFCCONTROL_OP_RESET:
-        perfc_copy_info(pc->desc);
+        perfc_copy_info(pc->desc, pc->val);
         perfc_reset(0);
         rc = 0;
         break;
 
     case DOM0_PERFCCONTROL_OP_QUERY:
-        perfc_copy_info(pc->desc);
+        perfc_copy_info(pc->desc, pc->val);
         rc = 0;
         break;
 
@@ -237,6 +243,9 @@ int perfc_control(dom0_perfccontrol_t *pc)
 
     spin_unlock(&lock);
 
+    pc->nr_counters = NR_PERFCTRS;
+    pc->nr_vals = perfc_nbr_vals;
+
     return rc;
 }
 
index afaf4d5c652eb41a12cc72641716dc37638a5620..d211ca1624cc5b0ceab9f48deafd33e6529efe79 100644 (file)
@@ -361,17 +361,20 @@ DEFINE_XEN_GUEST_HANDLE(dom0_read_memtype_t);
 struct dom0_perfc_desc {
     char         name[80];             /* name of perf counter */
     uint32_t     nr_vals;              /* number of values for this counter */
-    uint32_t     vals[64];             /* array of values */
 };
 typedef struct dom0_perfc_desc dom0_perfc_desc_t;
 DEFINE_XEN_GUEST_HANDLE(dom0_perfc_desc_t);
+typedef uint32_t dom0_perfc_val_t;
+DEFINE_XEN_GUEST_HANDLE(dom0_perfc_val_t);
 
 struct dom0_perfccontrol {
     /* IN variables. */
     uint32_t       op;                /*  DOM0_PERFCCONTROL_OP_??? */
     /* OUT variables. */
-    uint32_t       nr_counters;       /*  number of counters */
+    uint32_t       nr_counters;       /*  number of counters description  */
+    uint32_t       nr_vals;                      /*  number of values  */
     XEN_GUEST_HANDLE(dom0_perfc_desc_t) desc; /*  counter information (or NULL) */
+    XEN_GUEST_HANDLE(dom0_perfc_val_t) val;   /*  counter values (or NULL)  */
 };
 typedef struct dom0_perfccontrol dom0_perfccontrol_t;
 DEFINE_XEN_GUEST_HANDLE(dom0_perfccontrol_t);